import React, { Component } from 'react';
import * as Tabs from '@radix-ui/react-tabs';
import * as Select from '@radix-ui/react-select';
import { connect } from 'react-redux';
import { withConsumer } from '../../context';
import TextareaAutosize from 'react-textarea-autosize';
import styles from './index.module.scss';
import Image from 'next/image';
import {
  Sparkles,
  ChevronDown,
  ArrowRight,
  Square,
  Paperclip,
  Server,
  Star,
  Plus,
} from 'lucide-react';

import router from 'next/router';
import { template_list, applied_list } from '@/api/ai';
import { toast } from '@/components/basicComp/Toast';
import env from '@/consts/environment';
import { parse } from 'partial-json';
import { update } from '@/utils/immutableUtil';
import ModelSelect from './ModelSelect';
import OptionsComp from './OptionsComp';
import AvaliableSelect from './AvaliableSelect';
import QuickCommands from './QuickCommands';
import McpSelect from './McpSelect';
import ConfirmDialog from '@/components/basicComp/Confirm';
import { intersection } from 'lodash';

import SetText from './SetText';
import BlurReveal from '@/components/BlurReveal/index';

@withConsumer
@connect(({ ppt }) => ({
  selectedChat: ppt.selectedChat,
  selectedChatInit: ppt.selectedChatInit,
  messages: ppt.messages,
  chatLoading: ppt.chatLoading,
  selectedModel: ppt.selectedModel,
}))
class Comp extends Component {
  textareaRef = React.createRef();
  state = {
    activeTab: 'mcp',
    inputValue: '',
    codeTemplateMap: {},
    selectedTemplate: 'auto',
    mcpList: [],
    selectMcp: 'none',
    toolsMsg: '',
    showMcpSelect: false,
    mentionQuery: '',
    showConfirmDialog: false,

    confirmTitle: '',

    // 选择过的 mcp
    mcpSelectList: [],

    /*** 新的 ***/
  };

  componentDidMount = () => {
    const {
      value: { setController },
    } = this.props;
    setController('ChatInput', this);
    this.getTemplateListData();
    this.getMcp();
    this.textareaRef?.current?.focus();
  };

  componentWillUnmount = () => {
    this.stopChat();
  };

  getTemplateListData = async () => {
    // var rs = await template_list();
    // if (rs.data?.code == 200) {
    //   var data = rs.data.data;
    //   var obj = {};
    //   data.forEach((item) => {
    //     obj[item.template_name] = item;
    //   });
    //   this.setState({ codeTemplateMap: obj });
    // }
  };

  getMcp = async () => {
    var rs = await applied_list();
    if (rs.data?.code == 200) {
      var data = rs.data.data;
      this.setState({ mcpList: data });
    }
  };

  handleTabChange = (value) => {
    const { inputFocus } = this.props.value;
    this.setState({ activeTab: value });
    setTimeout(() => {
      inputFocus();
    }, 100);
  };

  stopChat = () => {
    const {
      value: { changeState },
    } = this.props;
    this.isStopChat = true;
    if (this.heartbeatTimer) {
      clearTimeout(this.heartbeatTimer);
    }
    changeState({ chatLoading: false });
    console.log('Regenerating...');
  };

  handleSuggestionClick = (item) => {
    const { chatLoading } = this.props;
    if (chatLoading) return;
    this.setState({ inputValue: item.value, activeTab: 'artifacts' }, () => {
      this.handleSubmit();
    });
  };

  handleInputChange = (e) => {
    const inputValue = e.target.value;

    // Check for @ mentions
    // this.checkForMentions(inputValue);

    this.setState({ inputValue });
  };

  checkForMentions = (text) => {
    if (text.length < this.state.inputValue.length) {
      return;
    }

    if (text.length > 0 && text[text.length - 1] === '@') {
      this.setState({
        showMcpSelect: true,
        mentionQuery: '',
      });
      return;
    }
  };

  handleMcpSelectOpenChange = (open) => {
    this.setState(
      {
        showMcpSelect: open,
      },
      () => {
        // If dropdown is closed, focus on the textarea
        if (!open && this.textareaRef.current) {
          setTimeout(() => {
            this.textareaRef.current.focus();
          }, 0);
        }
      },
    );
  };

  selectMention = (serverName, serverItem) => {
    const { inputValue } = this.state;
    const lastAtIndex = inputValue.lastIndexOf('@');

    if (lastAtIndex !== -1) {
      // Replace the @query with the selected server
      const textBeforeAt = inputValue.substring(0, lastAtIndex);
      const textAfterQuery = inputValue.substring(
        lastAtIndex + this.state.mentionQuery.length + 1,
      );
      const newInputValue = `${textBeforeAt}@mcp:${serverName} ${textAfterQuery}`;

      var mcpSelectList = [...this.state.mcpSelectList, serverName];
      mcpSelectList = [...new Set(mcpSelectList)];
      this.setState({
        inputValue: newInputValue,
        showMcpSelect: false,
        mentionQuery: '',
        selectMcp: serverName,
        mcpSelectList: mcpSelectList,
      });

      // Focus the textarea and place cursor after the inserted mention
      setTimeout(() => {
        const textarea = this.textareaRef.current;
        if (textarea) {
          textarea.focus();
          const cursorPosition = textBeforeAt.length + serverName.length + 6; // +2 for @ and space
          textarea.setSelectionRange(cursorPosition, cursorPosition);
        }
      }, 0);
    }
  };

  handleSubmit = () => {
    const { inputValue, activeTab, codeTemplateMap, selectedTemplate } =
      this.state;
    const {
      chatLoading,
      selectedChat,
      selectedModel,
      value: { controller, changeState, scrollToBottom2 },
    } = this.props;
    var store = window.getStore();
    if (!inputValue.trim()) return;
    if (chatLoading) return;

    var { ppt } = store.getState();

    // 判断用户配置
    if (!selectedModel) {
      toast.error('Please configure your LLM settings');
      return;
    }

    changeState({
      chatLoading: true,
    });

    var queryText = this.getChatText(inputValue);

    // 添加用户消息
    var messages = [...ppt.messages];
    messages.push({
      role: 'user',
      content: [
        {
          type: 'text',
          text: queryText,
        },
      ],
      object: null,
    });

    // 机器人空数据
    messages.push({
      role: 'assistant',
      content: [],
      object: null,
      initData: true,
    });

    changeState({
      messages: messages,
      chatLoading: true,
    });

    setTimeout(() => {
      scrollToBottom2();
    }, 20);

    var reqData = {};

    // 处理代码逻辑
    if (activeTab == 'artifacts') {
      reqData = {
        ...reqData,
        code: true,
        artifacts_template_id: 0,
      };
      if (selectedTemplate != 'auto') {
        reqData.artifacts_template_id = codeTemplateMap[selectedTemplate].id;
      }
    }

    setTimeout(() => {
      this.sendMsg();
    }, 100);
  };

  closeMenu = () => {
    const {
      value: { setSidebar },
    } = this.props;
    var store = window.getStore();
    var { global } = store.getState();
    if (global.sidebarOpen) {
      setSidebar(false);
    }
  };

  sendMsg = async (params = {}, type) => {
    if (this.heartbeatTimer) {
      clearTimeout(this.heartbeatTimer);
    }

    const { inputValue, activeTab } = this.state;
    const {
      messages,
      selectedModel,
      value: { changeState, controller, getSandbox, scrollToBottom2 },
    } = this.props;

    var reqData = {};
    var mcp_name_list = [];

    if (activeTab == 'mcp') {
      mcp_name_list = this.getMcpByStr(inputValue);
      mcp_name_list = intersection(mcp_name_list, this.state.mcpSelectList);
    }
    var query = this.getChatText(inputValue);

    if (type != 'user_confirm') {
      this.setState({ inputValue: '' });
    }

    reqData = {
      conversation_id: this.props.selectedChat,
      // generator_id: 'c8f10817-0a23-4639-b74d-9b2e22faf27f',
      // generator_id: '6f24788b-a2c4-4d9f-82f0-8737692053c9',//贵
      generator_id: selectedModel,
      system:
        '你是个专业AI智能助手，善于人性化回答用户的问题，如有工具尽量考虑全面，可以一次调用多个工具',
      query: query,
      mcp_name_list: mcp_name_list,
      ...params,
    };

    this.lastReqData = {
      ...reqData,
      inputValue: inputValue,
    };

    try {
      var url = `${env.apiUrl}/agent/chat/default_chat_stream`;
      const response = await window?.fetch(url, {
        mode: 'cors',
        credentials: 'omit',
        method: 'POST',
        body: JSON.stringify(reqData),
        headers: {
          'Content-Type': 'application/json',
          Accept: 'text/event-stream',
          Authorization: localStorage.getItem('authToken'),
        },
      });

      //获取UTF8的解码
      const encode = new TextDecoder('utf-8');

      // 获取body的reader
      const reader = response.body.getReader();

      // 重置心跳定时器
      var resetHeartbeatTimer = () => {
        clearTimeout(this.heartbeatTimer);
        this.heartbeatTimer = setTimeout(() => {
          this.isStopChat = true;
          console.log('因心跳终止');
        }, 20000); // 20秒超时
      };

      // 启动心跳定时器
      resetHeartbeatTimer();

      var str = '';
      var str2 = '';

      // 循环读取reponse中的内容
      while (true) {
        const { done, value } = await reader.read();

        var close = async () => {
          clearTimeout(this.heartbeatTimer);
          changeState({ chatLoading: false }, () => {
            setTimeout(() => {
              scrollToBottom2();
            }, 200);
          });
          await reader.cancel();
        };

        if (done) {
          console.log('结束了');
          close();
          break;
        }

        if (this.isStopChat) {
          this.isStopChat = false;
          close();
          break;
        }

        // 解码内容
        const text = encode.decode(value);

        // 获取正常信息时，逐字追加输出
        if (text) {
          var attr = text.split('\n');

          attr.forEach((item) => {
            // 处理心跳
            if (item.startsWith(': ping')) {
              console.log('心跳了');
              resetHeartbeatTimer();
            }

            if (item.startsWith('data: ')) {
              var obj = item.split('data: ')[1];
              obj = JSON.parse(obj);

              console.log(obj);

              if (obj.conversation_id) {
                this.conversation_id = obj.conversation_id;
              }

              //错误
              if (obj.role == 'error') {
                toast.error(obj.content);
              }

              // 处理工具调用
              if (obj.finish_reason == 'tool_calls') {
                obj.tool_calls.forEach((ite) => {
                  str2 += ite.name;
                });
                this.setState({ toolsMsg: str2 });
              }

              // 用户弹窗确认
              if (obj.finish_reason == 'user_confirm') {
                this.user_confirm = obj.user_confirm;
                this.setState({ showConfirmDialog: true });
              }

              // 处理消息 (需要处理下 stop 拿id)
              if (obj.content || obj.finish_reason == 'stop') {
                str += obj.content;
                this.setMessage({
                  role: 'ai',
                  content: [
                    {
                      type: 'text',
                      text: str,
                      itemData: obj,
                    },
                  ],
                  initData: false,
                });
              }

              // 处理生成代码
              if (obj.type == 'code') {
                var content = obj.content || '';
                // Remove code block markers with any language identifier
                content = content.replace(/```[\w-]*\n?/g, '');
                str += content;
                str = str.replace(/^[\w-]*\n?/, '');
                if (str.length > 4) {
                  var itemObj = parse(str);
                  changeState({
                    fragment: itemObj,
                    openPreview: true,
                    currentTab: 'code',
                  });

                  setTimeout(() => {
                    this.closeMenu();
                  }, 100);

                  const content2 = [
                    { type: 'text', text: itemObj.commentary || '' },
                    { type: 'code', text: itemObj.code || '' },
                  ];

                  this.setMessage({
                    content: content2,
                    object: itemObj,
                    initData: false,
                  });
                }
              }
            }
          });
        }
      }

      // 新会话 id
      if (!reqData.conversation_id) {
        var selectedChat = this.conversation_id;
        changeState({ selectedChat: selectedChat });

        // 侧边栏
        var sidebar = controller.Left;
        if (!sidebar) return;
        sidebar.getList((data) => {
          var selectedItem = _.find(data, { id: this.conversation_id });
          if (selectedItem) {
            changeState({
              selectedChat: selectedItem.id,
              selectedItem: selectedItem,
            });
            if (typeof window !== 'undefined') {
              window.localStorage.setItem('selectedChat', selectedItem.id);
            }
          }
        });
      }

      // 处理code逻辑
      if (reqData.code == true) {
        var fragment = JSON.parse(str);
        var rs = await getSandbox(fragment);
        const result = await rs.json();

        changeState({
          openPreview: true,
          codeResult: result,
          itemIndex: messages.length - 1,
          currentTab: 'fragment',
        });

        setTimeout(() => {
          this.closeMenu();
        }, 100);

        var ChatInput = controller.ChatInput;
        if (ChatInput) {
          ChatInput.setMessage({ result });
        }
      }
    } catch (error) {
      console.log(error);
    } finally {
      changeState({
        chatLoading: false,
        mcpSelectList: [],
      });

      setTimeout(() => {
        scrollToBottom2();
      }, 50);

      // 处理toolsMsg
      setTimeout(() => {
        if (!this.user_confirm) {
          this.setState({ toolsMsg: '' });
        }
      }, 4000);
    }
  };

  setMessage = (item, index, isScroll = true) => {
    const {
      value: { changeState, scrollToBottom2 },
    } = this.props;
    var store = window.getStore();
    var { ppt } = store.getState();
    var messages = [...ppt.messages];

    var i = messages.length - 1;
    if (index !== undefined) i = index;

    messages[i] = { ...messages[i], ...item };
    changeState({ messages: messages });

    if (isScroll) {
      setTimeout(() => {
        scrollToBottom2();
      }, 20);
    }
  };

  renderPersonaDropdown() {
    const { codeTemplateMap, selectedTemplate } = this.state;
    return (
      <Select.Root
        value={selectedTemplate}
        onValueChange={(value) => this.setState({ selectedTemplate: value })}
      >
        <Select.Trigger
          className={styles.personaTrigger}
          aria-label="Select persona"
        >
          <div className={styles.personaButton}>
            <Select.Value placeholder="Persona" />
            <Select.Icon>
              <ChevronDown size={16} />
            </Select.Icon>
          </div>
        </Select.Trigger>

        <Select.Portal>
          <Select.Content
            className={styles.selectContent}
            position="popper"
            side="top"
            sideOffset={5}
            align="start"
          >
            <Select.Viewport>
              <Select.Item
                value="auto"
                key={'auto'}
                className={styles.selectItem}
              >
                <Select.ItemText>
                  <div className={styles.itemText}>
                    <Sparkles
                      className="flex text-[#a1a1aa]"
                      width={14}
                      height={14}
                      style={{ marginRight: '10px' }}
                    />
                    {'Auto'}
                  </div>
                </Select.ItemText>
              </Select.Item>
              {Object.entries(codeTemplateMap).map(([templateId, template]) => (
                <Select.Item
                  key={templateId}
                  value={templateId}
                  className={styles.selectItem}
                >
                  <Select.ItemText>
                    <div className={styles.itemText}>
                      <img
                        className="flex"
                        src={`${router.basePath}/img/templates/${templateId}.svg`}
                        alt={templateId}
                        width={14}
                        height={14}
                        style={{ marginRight: '10px' }}
                      />
                      {template.name}
                    </div>
                  </Select.ItemText>
                </Select.Item>
              ))}
            </Select.Viewport>
          </Select.Content>
        </Select.Portal>
      </Select.Root>
    );
  }

  renderActionButtons() {
    const { chatLoading } = this.props;
    const { inputValue, activeTab } = this.state;
    const isDisabled = false;

    return (
      <div className={styles.actionButtons}>
        <OptionsComp activeTab={activeTab} />

        {!chatLoading ? (
          <button
            className={styles.submitButton}
            disabled={isDisabled}
            onClick={this.handleSubmit}
          >
            <i
              className={'iconfont icon-fasong ' + styles.buttonIcon}
              style={{ fontSize: '15px' }}
            ></i>
          </button>
        ) : (
          <button
            className={styles.submitButton}
            disabled={isDisabled}
            onClick={() => {
              this.stopChat();
            }}
          >
            <Square size={16} className={styles.buttonIcon} />
          </button>
        )}
      </div>
    );
  }

  renderMcpDropdown() {
    const { mcpList, selectMcp } = this.state;
    return (
      <Select.Root
        value={selectMcp}
        onValueChange={(value) => this.setState({ selectMcp: value })}
      >
        <Select.Trigger
          className={styles.personaTrigger}
          aria-label="Select persona"
        >
          <div className={styles.personaButton}>
            <Server className="w-4 h-4" style={{ color: '#a1a1aa' }} />
            <Select.Value placeholder="Persona" />
            <Select.Icon>
              <ChevronDown size={16} />
            </Select.Icon>
          </div>
        </Select.Trigger>

        <Select.Portal>
          <Select.Content
            className={styles.selectContent}
            position="popper"
            side="top"
            sideOffset={5}
            align="start"
          >
            <Select.Viewport>
              <Select.Item
                value="none"
                key={'none'}
                className={styles.selectItem}
              >
                <Select.ItemText>
                  <div className={styles.itemText}>{'none'}</div>
                </Select.ItemText>
              </Select.Item>
              {mcpList.map((item) => (
                <Select.Item
                  key={String(item.id)}
                  value={String(item.id)}
                  className={styles.selectItem}
                >
                  <Select.ItemText>
                    <div className={styles.itemText}>{item.server_name}</div>
                  </Select.ItemText>
                </Select.Item>
              ))}
            </Select.Viewport>
          </Select.Content>
        </Select.Portal>
      </Select.Root>
    );
  }

  renderSuggestions() {
    return (
      <div className={styles.suggestionsContainer}>
        <div style={{ marginRight: '16px' }}>
          <AvaliableSelect mcpList={this.state.mcpList} />
        </div>

        <QuickCommands
          onValueChange={(item) => {
            this.handleSuggestionClick(item);
          }}
        />
      </div>
    );
  }

  onConfirmMcp = async () => {
    const {
      value: { changeState },
    } = this.props;
    this.setState({
      showConfirmDialog: false,
    });
    changeState({ chatLoading: true });
    var obj = {
      conversation_id: this.conversation_id,
      user_confirm: {
        id: this.user_confirm.id,
        user_confirmation_result: true,
      },
      ...this.lastReqData,
    };
    await this.sendMsg(obj, 'user_confirm');
    this.user_confirm = null;
  };

  onCancel = () => {
    const {
      value: { changeState },
    } = this.props;
    const { messages } = this.props;
    this.user_confirm = null;
    this.setState({
      showConfirmDialog: false,
      inputValue: this.lastReqData.inputValue,
      toolsMsg: '',
      mcpSelectList: this.lastReqData.mcp_name_list,
    });
    this.textareaRef.current.focus();

    //之前添加2个消息清空掉
    var msgList = [...messages];
    msgList.splice(-2);
    changeState({ messages: msgList });
  };

  //返回 mcp 数组
  getMcpByStr = (str) => {
    const mcpParams =
      str
        .match(/@mcp:[^\s]+/g) // 匹配完整的 @mcp:参数
        ?.flatMap((param) => param.split(':')[1]) || []; // 提取参数部分
    return mcpParams;
  };

  //剔除所有 @mcp:xxx 部分，返回剩余文字
  getChatText = (str) => {
    if (!str) return '';
    // 去除所有 @mcp:xxx
    return str
      .replace(/@mcp:[^\s]+/g, '')
      .replace(/\s+/g, ' ')
      .trim();
  };

  shouldComponentUpdate = (np, ns) => update.call(this, np, ns);
  render() {
    const {
      activeTab,
      inputValue,
      mcpList,
      showMcpSelect,
      mentionQuery,
      toolsMsg,
    } = this.state;
    const { selectedChat, selectedChatInit, messages } =
      this.props;

    var isCenter = false;
    if (!selectedChat && selectedChatInit && messages.length == 0) {
      isCenter = true;
    }

    if (!selectedChatInit) return <></>;

    var placeholder = 'Describe your app...';
    return (
      <div className={styles.container}>
        {!selectedChat && messages.length == 0 && (
          <div className={styles.hintTitle}>
            <BlurReveal duration={1900}>
              <div style={{ fontWeight: 450, marginBottom: 8 }} className={styles.hint}>👋Hello!</div>
            </BlurReveal>
            <BlurReveal duration={2300}>
              <div style={{ fontSize: 40, marginBottom: 40 }} className={styles.hint}>Ready to create a slideshow?</div>
            </BlurReveal>
          </div>
        )}

        {toolsMsg && (
          <div className={styles.toolsMsg}>
            <i className="iconfont icon-tongzhi"></i>
            {toolsMsg}
          </div>
        )}

        <SetText />

        <div className={styles.inputWrapper}>
          {showMcpSelect && (
            <div className={styles.mentionPopup}>
              <McpSelect
                mcpList={mcpList}
                open={showMcpSelect}
                onSelect={this.selectMention}
                onOpenChange={this.handleMcpSelectOpenChange}
              />
            </div>
          )}

          <div style={{ width: '100%', flex: '1' }}>
            <TextareaAutosize
              autoFocus={true}
              className={styles.input}
              placeholder={placeholder}
              value={inputValue}
              onChange={this.handleInputChange}
              onKeyDown={(e) => {
                if (e.key === '@' && activeTab == 'mcp') {
                  // this.setState({ showMcpSelect: true });
                  return;
                }

                if (e.key === 'Enter' && !e.shiftKey) {
                  e.preventDefault();
                  this.handleSubmit();
                } else if (e.key === 'Escape' && this.state.showMcpSelect) {
                  e.preventDefault();
                  // this.setState({ showMcpSelect: false }, () => {
                  //   // Focus on the textarea after closing dropdown
                  //   if (this.textareaRef.current) {
                  //     setTimeout(() => {
                  //       this.textareaRef.current.focus();
                  //     }, 0);
                  //   }
                  // });
                }
              }}
              minRows={1}
              maxRows={5}
              ref={this.textareaRef}
              id="chat-textarea"
            />
          </div>

          <div className={styles.options}>
            <div className={styles.optionsLeft}>
              <div className={styles.chatInput}>
                <Tabs.Root
                  value={'artifacts'}
                // onValueChange={this.handleTabChange}
                >
                  <Tabs.List
                    className={styles.tabs}
                    aria-label="Choose interface type"
                  >
                    <Tabs.Trigger className={styles.tab} value="mcp">
                      Chat
                    </Tabs.Trigger>
                    <Tabs.Trigger className={styles.tab} value="artifacts">
                      Build
                    </Tabs.Trigger>
                  </Tabs.List>
                </Tabs.Root>
              </div>
            </div>
            <div className={styles.optionsRight}>
              <ModelSelect />
              {this.renderActionButtons()}
            </div>
          </div>
        </div>

        {isCenter && (
          <div className={styles.callWord} style={{ height: '80px' }}>
            {/* {this.renderSuggestions()} */}
          </div>
        )}

        <ConfirmDialog
          isOpen={this.state.showConfirmDialog}
          title={`Confirm Mcp`}
          message={this?.user_confirm?.message}
          onCancel={() => {
            this.onCancel();
          }}
          onConfirm={async () => {
            this.onConfirmMcp();
          }}
          cancelText="Cancel"
          confirmText="Submit"
        />
      </div>
    );
  }
}

export default Comp;
